# -*- coding: utf-8 -*-
import tkinter as tk
import random
from collections import deque

# 简单版连连看（tkinter）
# 规则：选择两个相同的符号，如果可以通过不超过两次转弯的折线路径连接（路径只能横竖，且不能穿过其他方块），则消除。

ROWS = 8  # 可玩行数
COLS = 10 # 可玩列数
MAX_TURNS = 2

EMOJIS = [
    "🍎","🍐","🍊","🍋","🍌","🍉","🍇","🍓",
    "🍒","🥝","🥥","🍍","🥕","🌽","🍆","🥑",
    "🍄","🥔","🍅","🥬","🧀","🍞","🥐","🍪",
    "🍩","🍰","🍫","🍿","🍜","🍣","🍤","🍱"
]

class Lianliankan:
    def __init__(self, master, rows=ROWS, cols=COLS):
        self.master = master
        self.rows = rows
        self.cols = cols
        self.frame = tk.Frame(master)
        self.frame.pack(padx=10, pady=10)

        self.info = tk.Label(self.master, text="")
        self.info.pack()

        # 添加菜单栏：包含“再生成一个菜单（新局）”、“重排”和“退出”
        menubar = tk.Menu(self.master)
        game_menu = tk.Menu(menubar, tearoff=0)
        game_menu.add_command(label="再生成一个菜单", command=self.restart)
        game_menu.add_command(label="重排 (Shuffle)", command=self.shuffle)
        game_menu.add_separator()
        game_menu.add_command(label="退出", command=self.master.quit)
        menubar.add_cascade(label="游戏", menu=game_menu)
        self.master.config(menu=menubar)

        ctrl = tk.Frame(self.master)
        ctrl.pack(pady=6)
        tk.Button(ctrl, text="重排 (Shuffle)", command=self.shuffle).pack(side=tk.LEFT, padx=4)
        tk.Button(ctrl, text="重开 (Restart)", command=self.restart).pack(side=tk.LEFT, padx=4)

        self.create_game()

    def create_game(self):
        # 带外层空白边界的矩阵，方便路径出界连接
        self.grid = [[0] * (self.cols + 2) for _ in range(self.rows + 2)]
        total = self.rows * self.cols
        assert total % 2 == 0, "总格子数需为偶数"

        # 选择符号并成对分配
        need_pairs = total // 2
        symbols = []
        # 选取足够的 emoji
        pool = EMOJIS.copy()
        random.shuffle(pool)
        while len(pool) < need_pairs:
            pool += EMOJIS
        symbols = pool[:need_pairs]
        items = symbols * 2
        random.shuffle(items)

        # 填充到 grid 内（1..rows, 1..cols）
        it = iter(items)
        for r in range(1, self.rows + 1):
            for c in range(1, self.cols + 1):
                self.grid[r][c] = next(it)

        # UI 按钮矩阵
        self.buttons = {}
        for r in range(1, self.rows + 1):
            for c in range(1, self.cols + 1):
                b = tk.Button(self.frame, text=self.grid[r][c], width=3, height=1,
                              command=lambda rr=r, cc=c: self.on_click(rr, cc))
                b.grid(row=r, column=c, padx=2, pady=2)
                self.buttons[(r, c)] = b

        self.first = None
        self.update_info()

    def update_info(self):
        remaining = sum(1 for r in range(1, self.rows+1) for c in range(1, self.cols+1) if self.grid[r][c])
        self.info.config(text=f"剩余格子: {remaining}（配对数 {remaining//2}）")

    def restart(self):
        # 清除原 UI
        for b in self.buttons.values():
            b.destroy()
        self.frame.destroy()
        self.frame = tk.Frame(self.master)
        self.frame.pack(padx=10, pady=10)
        self.create_game()

    def shuffle(self):
        # 将所有符号取出，随机重排
        items = [self.grid[r][c] for r in range(1, self.rows+1) for c in range(1, self.cols+1) if self.grid[r][c]]
        random.shuffle(items)
        it = iter(items)
        for r in range(1, self.rows + 1):
            for c in range(1, self.cols + 1):
                if self.grid[r][c]:
                    self.grid[r][c] = next(it)
                    self.buttons[(r, c)].config(text=self.grid[r][c], state=tk.NORMAL, bg='SystemButtonFace')
        self.first = None
        self.update_info()

    def on_click(self, r, c):
        if not self.grid[r][c]:
            return
        if self.first is None:
            self.first = (r, c)
            self.buttons[(r, c)].config(bg='lightblue')
            return
        (r1, c1) = self.first
        # 取消自己再次点击
        if (r1, c1) == (r, c):
            self.buttons[(r1, c1)].config(bg='SystemButtonFace')
            self.first = None
            return

        # 不同符号直接取消选择
        if self.grid[r1][c1] != self.grid[r][c]:
            # 快速闪烁提示
            self.buttons[(r1, c1)].config(bg='pink')
            self.master.after(200, lambda: self.buttons[(r1, c1)].config(bg='SystemButtonFace'))
            self.first = None
            return

        # 符号相同，检测是否可连接
        if self.can_connect((r1, c1), (r, c)):
            # 移除
            self.grid[r1][c1] = 0
            self.grid[r][c] = 0
            self.buttons[(r1, c1)].config(text='', state=tk.DISABLED, bg='SystemButtonFace')
            self.buttons[(r, c)].config(text='', state=tk.DISABLED, bg='SystemButtonFace')
            self.first = None
            self.update_info()
            if self.check_win():
                self.info.config(text="恭喜！你已消除全部方块 🎉")
        else:
            # 提示并取消选择
            self.buttons[(r1, c1)].config(bg='pink')
            self.master.after(200, lambda: self.buttons[(r1, c1)].config(bg='SystemButtonFace'))
            self.first = None

    def check_win(self):
        for r in range(1, self.rows+1):
            for c in range(1, self.cols+1):
                if self.grid[r][c]:
                    return False
        return True

    def can_connect(self, a, b):
        # BFS，状态：位置 + 来向方向 + 转弯数
        (r0, c0) = a
        (rT, cT) = b
        R = self.rows + 2
        C = self.cols + 2

        # 临时把起点设为空以允许穿越
        start_val = self.grid[r0][c0]
        target_val = self.grid[rT][cT]

        # BFS 队列元素 (r, c, dir, turns)
        # dir: 0 up,1 right,2 down,3 left, None 表示起始
        dirs = [(-1,0),(0,1),(1,0),(0,-1)]
        q = deque()
        visited = [[[999]* (MAX_TURNS+2) for _ in range(C)] for __ in range(R)]
        # 允许先从起点向4个方向扩展
        for d_idx, (dr,dc) in enumerate(dirs):
            nr, nc = r0 + dr, c0 + dc
            if 0 <= nr < R and 0 <= nc < C:
                # 可以走：格子为空（0）或是目标点
                if (nr, nc) == (rT, cT) or self.is_empty(nr, nc):
                    visited[nr][nc][0] = d_idx
                    q.append((nr, nc, d_idx, 0))

        while q:
            r, c, dir_idx, turns = q.popleft()
            if turns > MAX_TURNS:
                continue
            if (r, c) == (rT, cT):
                return True
            # 继续向四个方向扩展
            for nd, (dr,dc) in enumerate(dirs):
                nr, nc = r + dr, c + dc
                nturns = turns + (0 if nd == dir_idx else 1)
                if nturns > MAX_TURNS:
                    continue
                if not (0 <= nr < R and 0 <= nc < C):
                    continue
                # 可以走：为空或是目标
                if (nr, nc) != (rT, cT) and not self.is_empty(nr, nc):
                    continue
                # 防止重复状态（位置+turns）
                # visited 存储最早达到该格的 dir（简化判断），这里用 turns 作为维度
                if visited[nr][nc][nturns] <= nd:
                    # 已经有一个更优或等优路径到达（用方向粗略比较）
                    pass
                else:
                    visited[nr][nc][nturns] = nd
                    q.append((nr, nc, nd, nturns))
        return False

    def is_empty(self, r, c):
        # r,c 在 0..rows+1, 0..cols+1 的范围内
        # 边界（0 或 rows+1）默认视为空
        if r < 0 or c < 0 or r >= len(self.grid) or c >= len(self.grid[0]):
            return True
        return self.grid[r][c] == 0


if __name__ == '__main__':
    root = tk.Tk()
    root.title('连连看 - 简易版')
    app = Lianliankan(root)
    root.mainloop()
